/*
 * $Id: Thread.m,v 1.7 2006/06/03 16:49:24 bacon Exp $
 */

#include <xpo/bas/Thread.h>
#include <xp/bas/assert.h>

static int __run_thr (xp_thr_t* thr);
static int __run_runnable (xp_thr_t* thr);

@implementation XpThread

+ (XpThread*) start: (XpObject<XpRunnable>*) runnable
{
	int n;
	XpThread* t = [self new];
	if (t == nil) return nil;

	n = [t start: runnable];
	if (n == -1) {
		[t free];
		return nil;
	}
	return t;
}

- (id) init 
{
	[super init];
	thr_target = nil;
	xp_ensure (
		xp_thr_open (&thr, __run_thr, self) != XP_NULL
	);
	return self;
}

- (void) free
{
	xp_thr_close (&thr);
	[super free];
}

- (int) start
{
	return xp_thr_start (&thr, 0);
}

- (int) start: (XpObject<XpRunnable>*) runnable
{
	thr_target = runnable;
	return xp_thr_start (&thr, XP_THR_NEW_ROUTINE, __run_runnable);
}

- (int) stop
{
	return xp_thr_stop (&thr);
}

- (int) join
{
	return xp_thr_join (&thr);
}

- (void) sleep: (xp_time_t) msecs
{
	xp_sleep (msecs);
}

- (int) run
{
	[self subclassResponsibility];
	return -1;
}

@end

static int __run_thr (xp_thr_t* thr)
{
	XpThread* t = (XpThread*)thr->__user_data;	
	return [t run];
}

static int __run_runnable (xp_thr_t* thr)
{
	XpThread* t = (XpThread*)thr->__user_data;	
	id<XpRunnable> runnable = t->thr_target;
#if 0
	xp_assert (runnable != nil && 
		[runnable conformsTo: @protocol(XpRunnable)]);
#endif
	return [runnable run];	
}
